package com.account.book.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.account.book.common.constant.UploadPathConstant;
import com.account.book.common.exception.BasicInfoException;
import com.account.book.common.exception.BasicInfoStatusEnum;
import com.account.book.entity.CategoryBase;
import com.account.book.enums.DataStatusEnum;
import com.account.book.mapper.CategoryBaseMapper;
import com.account.book.request.CategoryBaseReqVo;
import com.account.book.service.CategoryBaseService;
import com.account.book.util.CosClientUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.Date;
import java.util.List;

/**
 * @author liang-hw
 * @className CategoryBaseServiceImpl
 * @description 分类表
 * @date 2023/11/09 14:54:22
 */
@Service
public class CategoryBaseServiceImpl extends ServiceImpl<CategoryBaseMapper, CategoryBase> implements CategoryBaseService {
    private static final Logger logger = LoggerFactory.getLogger(UploadFileServiceImpl.class);
    @Autowired
    private CosClientUtil cosClientUtil;

    /**
     * @param
     * @return @return {@link List }<{@link Tree }<{@link String }>>
     * @author liang-hw
     * @description 查询基础分类信息
     * @date 2023/12/05 10:10:13
     */
    @Override
    public List<Tree<String>> findCategoryBaseList(Integer type) {
        QueryWrapper<CategoryBase> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(CategoryBase::getStatus, DataStatusEnum.ENABLE.getValue())
                .eq(null != type, CategoryBase::getType, type);
        List<CategoryBase> categoryBaseList = baseMapper.selectList(queryWrapper);
        List<Tree<String>> tree = constructTreeNodes(categoryBaseList);
        return tree;
    }

    /**
     * @param @param     categoryBaseReqVo
     * @param uploadFile
     * @return
     * @author liang-hw
     * @description 保存基础分类
     * @date 2023/12/05 10:10:27
     */
    @Override
    @Transactional
    public void save(CategoryBaseReqVo categoryBaseReqVo, MultipartFile uploadFile) {
        QueryWrapper<CategoryBase> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(CategoryBase::getName, categoryBaseReqVo.getName());
        queryWrapper.lambda().eq(CategoryBase::getType, categoryBaseReqVo.getType());
        Long count = baseMapper.selectCount(queryWrapper);
        if (count != null && count > 0) {
            throw new BasicInfoException(BasicInfoStatusEnum.SYSTEM_ERROR.getCode(),
                    "基础分类已经存在");
        }
        String path = "";
        //收入分类
        if (categoryBaseReqVo.getType() == 0) {
            path = UploadPathConstant.CATEGORY_BASE_PATH + "/" + "income";
        } else if (categoryBaseReqVo.getType() == 1) {
            path = UploadPathConstant.CATEGORY_BASE_PATH + "/" + "disburse";
        }
        String url = cosClientUtil.upLoadFile(uploadFile, path);
        if (StringUtils.isEmpty(url)) {
            throw new BasicInfoException(BasicInfoStatusEnum.SYSTEM_ERROR.getCode(),
                    "文件上传失败");
        } else {
            logger.info("上传成功url地址：{}" + url);
            CategoryBase categoryBase = new CategoryBase();
            final CopyOptions copyOptions = CopyOptions.create();
            copyOptions.setOverride(false);
            copyOptions.setIgnoreNullValue(true);
            BeanUtil.copyProperties(categoryBaseReqVo, categoryBase, copyOptions);
            if (categoryBaseReqVo.getStatus() == null) {
                categoryBase.setStatus(DataStatusEnum.ENABLE.getValue());
            }
            categoryBase.setIcon(url);
            categoryBase.setCreateTime(new Date());
            categoryBase.setCreateBy("admin");
            baseMapper.insert(categoryBase);
        }
    }

    /**
     * @param @param categoryBaseReqVo
     * @return
     * @author liang-hw
     * @description 更新分类
     * @date 2023/12/05 09:54:20
     */
    @Override
    public void updateCategory(CategoryBaseReqVo categoryBaseReqVo) {
        CategoryBase categoryBase = new CategoryBase();
        final CopyOptions copyOptions = CopyOptions.create();
        copyOptions.setOverride(false);
        copyOptions.setIgnoreNullValue(true);
        BeanUtil.copyProperties(categoryBaseReqVo, categoryBase, copyOptions);
        UpdateWrapper<CategoryBase> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(CategoryBase::getName, categoryBaseReqVo.getName());
        updateWrapper.lambda().eq(CategoryBase::getType, categoryBaseReqVo.getType());
        baseMapper.update(categoryBase, updateWrapper);
    }

    /**
     * @param @param type
     * @param name
     * @return
     * @author liang-hw
     * @description 移除基础分类
     * @date 2023/12/05 09:42:54
     */
    @Override
    public void remove(Integer type, String name) {
        UpdateWrapper<CategoryBase> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(CategoryBase::getName, name);
        updateWrapper.lambda().eq(CategoryBase::getType, type);
        baseMapper.delete(updateWrapper);
    }

    /**
     * @param
     * @return @return {@link List }<{@link Tree }<{@link String }>>
     * @author liang-hw
     * @description 构建树形结构
     * @date 2023/12/02 19:24:49
     */
    private List<Tree<String>> constructTreeNodes(List<CategoryBase> categoryBaseList) {
        //配置
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 最大递归深度
        treeNodeConfig.setDeep(3);
        List<Tree<String>> treeNodes = TreeUtil.build(categoryBaseList, "0", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId());
                    tree.setParentId(treeNode.getParentId());
                    tree.setName(treeNode.getName());
                    // 扩展属性 ...
                    tree.putExtra("icon", treeNode.getIcon());
                    tree.putExtra("type", treeNode.getType());
                    tree.putExtra("weightIcon", treeNode.getWeightIcon());
                });
        return treeNodes;
    }
}
